﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Oxite.Infrastructure;
using Oxite.Models;
using Oxite.Results;
using Oxite.Extensions;
using Oxite.ViewModels;
using Oxite.Skinning;
using ECube.Web.CMS.Models;
using ECube.Web.CMS.Services;
using ECube.SEC.Services;

using ECube.SEC.Filters;
namespace ECube.Web.CMS.Filters
{
    public class UrlAuthorizationFilter : IAuthorizationFilter
    {

        private readonly IModulesLoaded modules;
        private readonly IAuthorizeService service;
        private readonly IUnityContainer container;

        public UrlAuthorizationFilter(IUnityContainer container,IModulesLoaded modules, IAuthorizeService service)
        {
            this.container = container;
            this.modules = modules;
            this.service = service;
        }
        #region IAuthorizationFilter 成员

        public void OnAuthorization(AuthorizationContext filterContext)
        {
            bool isAuthorized = true;
            string url = "~" + filterContext.HttpContext.Request.Url.AbsolutePath.Remove(0,filterContext.HttpContext.Request.ApplicationPath.Length);
            if (url == "~") url += "/";

            SiteMapNode node = SiteNavigatorService.Current.GetNode(url);
            IUser user = null;
            if (node != null)
            {
                if (node is MvcSiteMapNode)
                {
                    MvcSiteMapNode mvcNode = node as MvcSiteMapNode;

                    if (!mvcNode.AllowAnonymous)
                    {
                        IEnumerable<IOxiteAuthenticationModule> authenticationModules = modules.GetModules<IOxiteAuthenticationModule>().Reverse();
                        

                        foreach (IOxiteAuthenticationModule module in authenticationModules)
                        {
                            user = module.GetUser(filterContext.RequestContext);
                            if (user.IsAuthenticated)
                            {
                                if (!HasPermission(user, url))
                                {
                                    isAuthorized = false;
                                }
                                break;
                            }
                        }

                        if (user == null || !user.IsAuthenticated)
                        {
                            string signInUrl = authenticationModules.First().GetSignInUrl(filterContext.RequestContext);

                            if (filterContext.HttpContext.Request.IsAjaxRequest())
                                filterContext.Result = new JsonResult { Data = new AjaxRedirect(signInUrl) };
                            else
                                filterContext.Result = new RedirectResult(signInUrl);
                        }
                    }
                }
                else
                {
                    //if(!node.IsAccessibleToUser(filterContext.HttpContext)
                    //{

                    //}
                }
            } 
           
            if (!isAuthorized)
            {
                filterContext.Result = new UnauthorizedResult(container, new UserViewModel(user));
            }

        }

        #endregion

        public bool HasPermission( IUser user, string url)
        {
            string permissionKey = "URL:" + url;
            return this.service.GetPermissionsForUser(user).Any(p => permissionKey.Equals(p, StringComparison.OrdinalIgnoreCase));
        }
    }
}
